#include "game_area.h"




#define gamearea_y 15
#define gamearea_x 25

Game_Area::Game_Area(QWidget *parent) : QWidget(parent)
{

     mytimer=new QTimer(this);
     connect(mytimer,&QTimer::timeout,this,&Game_Area::mytimer_update_blocks);
}



void Game_Area::New_Game()
{
     /*初始化*/
     Gamescore=0;    //分数复位0
     emit Gamescore_change(Gamescore);
     Gamelevel=1;
     emit Gamelevel_change(Gamelevel);

     FixedBlocks.pointArray.clear();
     NextBlocks.pointArray.clear();
     CurmovingBlocks.pointArray.clear();

     /*下落的方块和下一次出现的方块图形初始化*/
     CurmovingBlocks.InitNew(QTime::currentTime().msec());    //利用QTime产生随机数
     CurmovingBlocks_color=setColor();      //颜色随机变化
     CurmovingBlocks.move(gamearea_x/2-1,0);

     NextBlocks.InitNew(QTime::currentTime().second());    //防止与当前方块形状一致
     NextBlocks_color=setColor();   //颜色随机变化
     emit NextBlocks_change(NextBlocks.mType,NextBlocks.mShape,NextBlocks_color);

     /*定时器*/
     Timer_interval=set_timer_interval(Gamescore);
     mytimer->start(Timer_interval);
}




void Game_Area::paintEvent(QPaintEvent *event)
{
      draw_frame();             //绘制边框
      draw_droppingBlocks();       //正在下落的方块
      draw_fixedBlocks();          //固定住的方块
      update();
}



void Game_Area::draw_frame()
{

   QPainter painter(this);
   painter.setPen(Qt::SolidLine);
   QLineF pointL[4];
   pointL[0].setLine(0,0,878,0);
   pointL[1].setLine(0,0,0,525);
   pointL[2].setLine(878,0,878,525);
   pointL[3].setLine(0,525,878,525);
   painter.drawLines(pointL, 4);
}





QColor Game_Area::setColor()
{
    int colorR, colorG, colorB;
    while(1)
    {
        colorR = rand()%256;
        colorG = rand()%256;
        colorB = rand()%256;

        if(colorR == 248 || colorG ==237 || colorB ==212)
        {
            continue;
        }
        else
        {
            break;
        }
    }
    QColor color(colorR, colorG, colorB);
    return color;
}



void Game_Area::keypressed(int key)
{

    if(key==Qt::Key_Left)
    {
        CurmovingBlocks.move(-1,0);
        if(hitSides()||hitFixblocks())
        {
                CurmovingBlocks.move(1,0);
                return;
        }
    }
    if(key==Qt::Key_Right)
    {
        CurmovingBlocks.move(1,0);
        if(hitSides()||hitFixblocks())
        {
                CurmovingBlocks.move(-1,0);
                return;
        }
    }
    if(key==Qt::Key_Down)
    {
            CurmovingBlocks.move(0,1);
            if(hitBottom()||hitFixblocks())   //落至底部或者固定方块
            {
                 CurmovingBlocks.move(0,-1);
                 return;
            }
    }
    if(key==Qt::Key_Up)
    {
        change_mShape(1);      //变化方块形状
    }
    if(key==Qt::Key_Control)
    {
        while (1)
        {
            CurmovingBlocks.move(0,1);
            if(hitBottom()||hitFixblocks())    //落至底部或者固定方块
            {
                    CurmovingBlocks.move(0,-1);
                    break;
            }

        }
        return;
    }
}




void Game_Area::change_mShape(int add)
{
    int direction=(CurmovingBlocks.mShape+add)%4;
    CurmovingBlocks.draw_block(CurmovingBlocks.mType,direction);
}



bool Game_Area::hitSides()
{
    for(int i=0;i<CurmovingBlocks.pointArray.count();i++)
    {
        if((CurmovingBlocks.pointArray[i].x()>gamearea_x-1)||(CurmovingBlocks.pointArray[i].x()<0))    //落至底部或者固定方块
        {
            return true;
        }
    }
    return false;
}



bool Game_Area::hitBottom()
{
    for(int i=0;i<CurmovingBlocks.pointArray.count();i++)
    {
        if(CurmovingBlocks.pointArray[i].y()>gamearea_y-1)    //落至底部或者固定方块
        {
            return true;
        }
    }
    return false;
}



bool Game_Area::hitFixblocks()
{
    for(int i=0;i<CurmovingBlocks.pointArray.count();i++)
    {
        if(FixedBlocks.pointArray.contains(CurmovingBlocks.pointArray[i]))    //落至底部或者固定方块
        {
            return true;
        }
    }
    return false;
}



void Game_Area::draw_fixedBlocks()
{
    QPainter painter(this);
    painter.setBrush(QColor("#696969"));
    painter.setPen(QPen(QColor(Qt::black),2));
    FixedBlocks.draw(painter);
}



void Game_Area::draw_droppingBlocks()
{
    QPainter painter(this);
    painter.setBrush(CurmovingBlocks_color);
    painter.setPen(QPen(QColor(Qt::black),2));
    CurmovingBlocks.draw(painter);
}




bool Game_Area::isContinue()
{
    for(int i=0;i<CurmovingBlocks.pointArray.count();i++)
    {
        if(CurmovingBlocks.pointArray[i].y()>gamearea_y-1)
            return true;
         if(FixedBlocks.pointArray.contains(CurmovingBlocks.pointArray[i]))
            return true;
    }
    return false;
}


bool Game_Area::hitTop()
{
    for(int i=0;i<CurmovingBlocks.pointArray.count();i++)
    {
        if(CurmovingBlocks.pointArray[i].y()==1)
            return true;
    }
    return false;
}



void Game_Area::rowFull()
{
        for(int col=0;col<gamearea_y;col++)
        {
            int nCount=0;
            for(int row=0;row<gamearea_x;row++)
            {
                if(FixedBlocks.pointArray.contains(QPoint(row,col)))
                      nCount++;
            }
            if(nCount>gamearea_x-1)
            {
                deleteRow(col);
                Gamescore+=gamearea_x;
                Timer_interval=set_timer_interval(Gamescore);
                mytimer->setInterval(Timer_interval);
                emit Gamelevel_change(Gamelevel);
                emit Gamescore_change(Gamescore);
                col--;
            }
        }
}


void Game_Area::deleteRow(int col)
{

    for(int i=0;i<FixedBlocks.pointArray.count();i++)
    {
        if(FixedBlocks.pointArray[i].y()==col)
        {
              FixedBlocks.pointArray.remove(i);
              i--;
        }
    }

    for(int i=0;i<FixedBlocks.pointArray.count();i++)
    {
        if(FixedBlocks.pointArray[i].y()<col)
        {
            FixedBlocks.pointArray[i].setY(FixedBlocks.pointArray[i].y()+1);
        }
    }
}




void Game_Area::mytimer_update_blocks()
{
       CurmovingBlocks.move(0,1);        //下落一格
       if(isContinue())                 //无法继续下落进入到if中
       {
           if(hitTop())                     //如果到达了顶部
           {
               CurmovingBlocks.move(0,-1);
               mybox=new QMessageBox(this);
               mybox->about(this,"WARNNING!","GAME OVER!");
               mytimer->stop();
               New_Game();
               return;
           }

           CurmovingBlocks.move(0,-1);
           FixedBlocks.pointArray<<CurmovingBlocks.pointArray;       //把当前方块加入到固定住的方块数组中

           rowFull();            //一行满了

           CurmovingBlocks.pointArray=NextBlocks.pointArray;         //当前方块=下一个方块形状
           CurmovingBlocks.mShape=NextBlocks.mShape;
           CurmovingBlocks.mType=NextBlocks.mType;
           CurmovingBlocks.mPos = QPoint(0,0);
           CurmovingBlocks_color=NextBlocks_color;
           CurmovingBlocks.move(gamearea_x/2-1,0);

           NextBlocks.pointArray.clear();                            //初始化下一个方块形状
           NextBlocks.InitNew(QTime::currentTime().msec());
           NextBlocks_color=setColor();      //刷新颜色
           emit NextBlocks_change(NextBlocks.mType,NextBlocks.mShape,NextBlocks_color);      //发送下一个方块形状信号给nextblock widget显示
       }

}




int Game_Area::set_timer_interval(int score)
{
    int interval=0;
    if(score<100)
    {
        interval=800;
        Gamelevel=1;
    }
    if((score>=100)&&(score<200))
    {
        interval=700;
        Gamelevel=2;
    }
    if((score>=200)&&(score<300))
    {
        interval=600;
        Gamelevel=3;
    }
    if((score>=300)&&(score<400))
    {
        interval=500;
        Gamelevel=4;
    }
    if((score>=400)&&(score<500))
    {
        interval=400;
        Gamelevel=5;
    }
    if((score>=500)&&(score<600))
    {
        interval=300;
        Gamelevel=6;
    }
    if((score>=600)&&(score<700))
    {
        interval=200;
        Gamelevel=7;
    }
    if(score>=700)
    {
        interval=100;
        Gamelevel=8;
    }
    return interval;
}
